package pl.edu.agh.neuraleconomy.ui.chart;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import lombok.Getter;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class LineChart {
	
	@Getter
	private Map<Integer, Date> timelineMap;
	private Map<Date, Integer> obverseTimelineMap;
	@Getter
	private int maxValue = 0;
	
	public JFreeChart createChart(ChartBean chartBean){
		JFreeChart chart = ChartFactory.createXYLineChart(chartBean.getChartName(), "Timeline", "Value", createDataSet(chartBean),
				PlotOrientation.VERTICAL, true, false,false);
		
		XYPlot xyPlot = (XYPlot) chart.getPlot();
		NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
        domain.setTickUnit(new NumberTickUnit(maxValue < 75 ? 1 : 5));
        domain.setVerticalTickLabels(true);
        
		return chart;
	}
	
	private XYDataset createDataSet(ChartBean chartBean){
		XYSeriesCollection data = new XYSeriesCollection();
		Collection<Date> timeline = mergeSeriesDates(chartBean.getSeries());
		createTimelineMap(timeline);
		for(SerieBean serie : chartBean.getSeries()){
			data.addSeries(getSerie(serie, timeline));
			XYSeries predictionSerie = getPrediction(serie, timeline);
			if(predictionSerie != null){
				data.addSeries(predictionSerie);
			}
		}

		return data;
	}
	
	private void createTimelineMap(Collection<Date> timeline){
		timelineMap = new HashMap<Integer, Date>();
		obverseTimelineMap = new HashMap<Date, Integer>();
		maxValue = 0;
		
		for(Date d : timeline){
			timelineMap.put(Integer.valueOf(maxValue), d);
			obverseTimelineMap.put(d, Integer.valueOf(maxValue));
			maxValue ++;
		}
		
		maxValue --;
	}
	
	private XYSeries getSerie(SerieBean serieBean, Collection<Date> timeline){
		XYSeries serie = new XYSeries(serieBean.getSerieName());
		
		int i = 0;
		for(Date d : timeline){
			int dateIndex = serieBean.getTimeLine().indexOf(d);
			if(dateIndex >= 0){
				serie.add(i, serieBean.getValues().get(dateIndex));
			}
			i++;
		}
		return serie;
	}
	
	private XYSeries getPrediction(SerieBean serieBean, Collection<Date> timeLine){
		PredictionSerieBean predictionSerie = serieBean.getPredictionSerie();
		if(predictionSerie == null){
			return null;
		}
		
		if(predictionSerie.getPredictionData() == null || predictionSerie.getPredictionDateFrom() == null){
			return null;
		}
		
		XYSeries serie = new XYSeries("Prediction ".concat(serieBean.getSerieName()));
		
		Integer startIndex = null;// obverseTimelineMap.get(predictionDateFrom);
		if(startIndex == null){
			timeLine.add(predictionSerie.getPredictionDateFrom());
			startIndex = (new ArrayList<Date>(timeLine)).indexOf(predictionSerie.getPredictionDateFrom());
			timeLine.remove(predictionSerie.getPredictionDateFrom());
		}
		
		for(int i=0; i<predictionSerie.getPredictionData().length;i++){
			serie.add(i+startIndex, predictionSerie.getPredictionData()[i]);
		}
		
		return serie;
	}
	
	private Collection<Date> mergeSeriesDates(List<SerieBean> series){
		TreeSet<Date> dates = new TreeSet<Date>(new Comparator<Date>() {

			public int compare(Date o1, Date o2) {
				return o1.compareTo(o2);
			}
		});
		for(SerieBean s : series){
			dates.addAll(s.getTimeLine());
		}
		return dates;
	}
}
